Android Service保活(二)之双进程守护

在上一章中,我们谈到了Android Service防杀的常用套路,随着越来越多的用户手机安装某卫士,某管家,常用的进程防杀套路并不能够很好的保证我们的APP进程常驻,因此本篇我给大家带来抗某卫士,某管家的双进程守护解决方案。

双进程守护,其实原理非常简单,网上也有很多博文讲述,今天我给大家用一个完整的案例来讲述。
假设我们的APP中开启了两个Service,分别是A和B,那么:
如果A守护B,则B挂掉的同时,A就应该把B启动起来,反之亦然,也就是说A和B应该是互相守护,无论谁被杀掉,对方就把它拉起来。

既然提到了两个Service,那么这两个Service就不能让它们同处在一个进程中,否则就会被一次性双杀。这里我们很容易想到IPC技术,在Android中通常我们可以使用AIDL来实现IPC操作。废话不多说,直接上代码。
先来看下项目整体结构:
项目结构

这里,我们定义两个Service,分别是LocalCastielService和RemoteCastielService,其中的RemoteCastielService我们通过属性配置android:process=”:com.castiel.remote” ,让它成为远端进程。

LocalCastielService.Java

public class LocalCastielService extends Service {

MyBinder myBinder;
private PendingIntent pintent;
MyServiceConnection myServiceConnection;

@Override
public void onCreate() {
    super.onCreate();
    if (myBinder == null) {
        myBinder = new MyBinder();
    }
    myServiceConnection = new MyServiceConnection();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    this.bindService(new Intent(this, RemoteCastielService.class), myServiceConnection, Context.BIND_IMPORTANT);
    Notification notification = new Notification(R.drawable.ic_launcher, "猴子服务启动中", System.currentTimeMillis());
    pintent = PendingIntent.getService(this, 0, intent, 0);
    notification.setLatestEventInfo(this, "猴子服务", "防止被杀掉!", pintent);

    // 设置service为前台进程,避免手机休眠时系统自动杀掉该服务
    startForeground(startId, notification);
    return START_STICKY;
}

class MyServiceConnection implements ServiceConnection {

    @Override
    public void onServiceConnected(ComponentName arg0, IBinder arg1) {
        Log.i("castiel", "远程服务连接成功");
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        // 连接出现了异常断开了,RemoteService被杀掉了
        Toast.makeText(LocalCastielService.this, "远程服务Remote被干掉", Toast.LENGTH_LONG).show();
        // 启动RemoteCastielService
        LocalCastielService.this.startService(new Intent(LocalCastielService.this, RemoteCastielService.class));
        LocalCastielService.this.bindService(new Intent(LocalCastielService.this, RemoteCastielService.class),
                myServiceConnection, Context.BIND_IMPORTANT);
    }

}

class MyBinder extends CastielProgressConnection.Stub {

    @Override
    public String getProName() throws RemoteException {
        return "Local猴子搬来的救兵 http://blog.csdn.net/mynameishuangshuai";
    }

}

@Override
public IBinder onBind(Intent arg0) {
    return myBinder;
}

}  

RemoteCastielService.java

public class RemoteCastielService extends Service {
MyBinder myBinder;
private PendingIntent pintent;
MyServiceConnection myServiceConnection;

@Override
public void onCreate() {
    super.onCreate();
    if (myBinder == null) {
        myBinder = new MyBinder();
    }
    myServiceConnection = new MyServiceConnection();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    this.bindService(new Intent(this,LocalCastielService.class), myServiceConnection, Context.BIND_IMPORTANT);
    Notification notification = new Notification(R.drawable.ic_launcher,
            "猴子服务启动中",
            System.currentTimeMillis());
    pintent=PendingIntent.getService(this, 0, intent, 0);
    notification.setLatestEventInfo(this, "猴子服务",
            "防止被杀掉!", pintent);

    //设置service为前台进程,避免手机休眠时系统自动杀掉该服务
    startForeground(startId, notification);
    return START_STICKY;
}

class MyServiceConnection implements ServiceConnection {

    @Override
    public void onServiceConnected(ComponentName arg0, IBinder arg1) {
        Log.i("castiel", "本地服务连接成功");
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        // 连接出现了异常断开了,LocalCastielService被杀死了
        Toast.makeText(RemoteCastielService.this, "本地服务Local被干掉", Toast.LENGTH_LONG).show();
        // 启动LocalCastielService
        RemoteCastielService.this.startService(new Intent(RemoteCastielService.this,LocalCastielService.class));
        RemoteCastielService.this.bindService(new Intent(RemoteCastielService.this,LocalCastielService.class), myServiceConnection, Context.BIND_IMPORTANT);
    }

}

class MyBinder extends CastielProgressConnection.Stub {

    @Override
    public String getProName() throws RemoteException {
        return "Remote猴子搬来的救兵 http://blog.csdn.net/mynameishuangshuai";
    }

}

@Override
public IBinder onBind(Intent arg0) {
    return myBinder;
}

}  

aidl文件

package com.castiel.aidl;
interface CastielProgressConnection{
String getProName();
}  

启动服务

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    // 启动本地服务和远程服务
    startService(new Intent(this, LocalCastielService.class));
    startService(new Intent(this, RemoteCastielService.class));
}  

通过以上代码可以看出,双进程守护实现代码非常简单,两个服务相互连接,Local服务连接着Remote服务,Remote服务又连接着Local服务,你中有我我中有你,一旦两个服务发现对方被杀掉,另一服务立刻会启动并连接它